/*
 * Application.cpp
 *
 *  Created on: 2018年1月2日
 *      Author: zhengboyuan
 */

#include "Application.h"
#include <signal.h>
#include "CLog.h"
#include "Socket.h"
#include "Path.h"
#include <stdio.h>
#include <cstdlib>


#ifdef WIN32
#else
#include <unistd.h>
#endif //

static Application* s_application = NULL;


static void SigInt_Handler(int n_signal)
{
	if (s_application)
	{
		s_application->exit();
	}
}

static void SigBreak_Handler(int n_signal)
{
	if (s_application)
	{
		s_application->exit();
	}
}


///

Application* Application::instance()
{
	return s_application;
}


Application::Application():
		m_name(),
		m_isDaemon(false),
        m_inited()
{
	s_application = this;
}

Application::~Application()
{
	if (checkResetInited())
	{
		uninitialize();
	}

	s_application = NULL;
}

AppConfig& Application::config()
{
	return AppConfig::instance();
}

void Application::setupSignal()
{
	signal(SIGINT, &SigInt_Handler);

	#ifdef WIN32
		signal(SIGBREAK, &SigBreak_Handler);
	#else

	#endif

}

void Application::setupLog()
{
	std::string logConfig = comn::Path::join(getAppDir(), "CLog.ini");
	if (comn::Path::exist(logConfig))
	{
		CLog::startup(logConfig.c_str());
	}
	else
	{
		CLog::setLogger(CLog::COUT, CLog::kNone, 0);
		CLog::setLogger(CLog::DEBUGWINDOW, CLog::kNone, 0);

		CLog::setFileParam(getLogFilePath().c_str(), 10, 5);
		CLog::setLogger(CLog::FILE);
	}
}

bool Application::initialize()
{
	setupLog();

	std::string configPath = getConfigPath();
	if (!config().load(configPath))
	{
		CLog::error("failed to load config. %s\n", configPath.c_str());
	}

	setupSignal();

	comn::Socket::startup();

	//
	CLog::info("configPath: %s\n", configPath.c_str());

    m_inited = init();

	return m_inited;
}

void Application::uninitialize()
{
	comn::Socket::cleanup();

	uninit();
}


std::string Application::getConfigPath()
{
	//CLog::debug("Application::getConfigPath: %s\n", m_name.c_str());

	std::string filename = m_name + ".ini";
	return comn::Path::join(getAppDir(), filename);
}

std::string Application::getLogFilePath()
{
	std::string filename = m_name + ".log";

	return comn::Path::join(getAppDir(), filename);
}

int Application::launch(int argc, char** argv)
{
	if (argc <= 0)
	{
		return -1;
	}

	std::string filepath = argv[0];
	comn::Path::abspath(filepath);
	if (m_name.empty())
	{
		std::string filename = comn::Path::basename(filepath);
		m_name = comn::Path::getFileTitle(filename);
	}

	m_dir = comn::Path::dirname(filepath);
	if (m_dir.empty())
	{
		m_dir = ".";
	}

	//printf("name:%s\n", m_name.c_str());
	//printf("dir:%s\n", m_dir.c_str());

	std::string daemonArg("-d");
	for (int i = 1; i < argc; i++)
	{
		if (daemonArg == argv[i])
		{
			m_isDaemon = true;
			break;
		}
	}

	if (m_isDaemon)
	{
	    daemonize();

		comn::Path::setCurDir(m_dir);
	}

	int rc = 0;
	if (initialize())
	{
		rc = run();
	}

    //CLog::debug("------ Application::launch uninitialize\n");

	if (checkResetInited())
	{
		uninitialize();
	}

	return rc;
}

void Application::setName(const std::string& name)
{
	m_name = name;
}

void Application::setDir(const std::string& dir)
{
    m_dir = dir;
}

void Application::setDaemon(bool isDaemon)
{
	m_isDaemon = isDaemon;
}

std::string Application::getAppDir()
{
	return m_dir;
}

std::string Application::getName()
{
	return m_name;
}

bool Application::checkResetInited()
{
	bool inited = m_inited;
	if (m_inited)
	{
		m_inited = false;
	}
	return inited;
}


void Application::daemonize()
{
#ifdef WIN32
   // pass
#else
    daemon(1, 0);
#endif
}


bool Application::init()
{
	return true;
}

void Application::uninit()
{
	//
}

void Application::terminate()
{
#ifdef _WIN32
	TerminateProcess(GetCurrentProcess(), 0);
#else

	::kill(getpid(), 9);
#endif	
}